$title  diskette I/O handler for CBIOS24"DHIO24" Date: 14/8-84
;
;
;
;       I/O port addresses
;
        dio     equ     030h    ;diskette controller
;
;
;       diskettcontroller command bytes
;
        rcom    equ     42h     ;read one sector
        wcom    equ     81h     ;write one sector
;
;
public  read,write,diskette
;
;       external data
;
extrn   ctb,rfunc,rmode,runit,rsector,fmode,buf
extrn   text3,rdma,rtrack,pu0,pu1,punit,MODE
;
;       external routines
;
extrn   seldsk,string
;
        CSEG
;
$e
;*******************************************************************************
;
;       read one block (128 byte)
;
;       input registers:        non
;
;       input parameters:       RUNIT requested unit number
;                               RTRACK requested track address
;                               RSECTOR requested sector address
;                               RDMA requested dma address
;
;       parameters changed:     RFUNC set to 0 for read
;                               CTB updated to current data
;                               FMODE set to 0 if diskette, 1 if harddisk
;
;       exit registers:         A = 0 no error, A <> 0 error during read
;
;       changed registers:      A and FLAGS
;
;*******************************************************************************
;
read:
        sub     a       ;set up read command
        jmp     waitio  ;to perform the actual i/o
$e
;*******************************************************************************
;
;       write one block (128 byte)
;
;       input registers:        non
;
;       input parameters:       RUNIT requested unit number
;                               RTRACK requested track address
;                               RSECTOR requested sector address
;                               RDMA requested dma address
;
;       parameters changed:     RFUNC set to 1 for write
;                               CTB updated to current data
;                               FMODE set to 0 if diskette, 1 if harddisk
;
;       exit registers:         A = 0 no error, A <> 0 error during read
;
;       changed registers:      A and FLAGS
;
;*******************************************************************************
;
write:  ;perform a write operation
        mvi     a,1     ;set up write command
$E
;       enter here from read and write to perform the actual i/o operation
;
waitio:
        push    h       ;save allregisters
        push    d
        push    b
        sta     rfunc   ;save command
        lda     MODE    ;get diskette density
        lxi     h,ctb+5 ;set pointer to current track parameter
        ANA     A       ;dd?
        JNZ     single  ;no, continue to single density operation
;
;       dd operation
;
        lxi     d,rsector;set pointer to requested sector parameter
        ldax    d       ;get requested sector address
        call    str     ;convert sector address to side and sector
        cmp     m       ;requested data area allready in buf
        jnz     changed ;no, continue to read one sector
        dcx     d
        dcx     h
        ldax    d       ;get requested track address
        rar             ;devide by 2
        ani     7fh     ;remove most sign bit
        inr     a       ;track offset track zero not used
        cmp     m       ;same track as last operation?
        jnz     changed ;no, continue to read one sector
        dcx     h       ;skip command byte
        dcx     h
        dcx     d
        ldax    d       ;get requested unit no
        ora     b       ;or with requested density and side info
        cmp     m       ;same unit, side and density as last operation?
        jz      doit    ;requested data block allredy in BUF
;
;   read the sector containing the reqested data block
;
changed:
        lxi     d,buf   ;set internal data buffer
        lxi     h,ctb+7
        mov     m,d
        dcx     h
        mov     m,e
        dcx     h
        lxi     d,rsector;get requested sector address
        ldax    d
        call    str     ;convert to side, density and sector address
        mov     m,a     ;set sector address
        dcx     h
        dcx     d
        ldax    d       ;get requested track address
        rar             ;/2
        ani     7fh     ;remove most sign. bit
        inr     a       ;add track offset
        mov     m,a     ;set track address
        dcx     h
        dcx     d
        mvi     m,rcom  ;set diskette read command
        dcx     h
        ldax    d       ;get requested unit no
        ora     b       ;or with side and density bits
        mov     m,a     ;set driva byte
        push    b
        call    diskette;execute diskette read operation
        pop     b
;
hdddcom:
        ana     a       ;error?
;
        jnz     dexit   ;yes, error exit, update stack and exit to user A <> 0
 
;
;       buf contains the requested data area
;       this point is commen for both harddisk and dd diskette operationes
;
doit:                   ;The internal buffer BUF contains two * 128 byte
                        ;of data.
        lxi     h,buf
        lxi     d,128   ;buffer length
        mov     a,c     ;C = 1 first part of BUF, C = 0 second part of BUF
        rar             ;first part?
        jc      doit1   ;yes
        dad     d       ;no, set pointer to second part
doit1:
        xchg            ;de source
        lhld    rdma    ;hl destination
        lda     rfunc   ;get reqested operation
        ana     a       ;read?
        jnz     wrtsec  ;no, move data from user buffer to BUF and write
        call    mov128  ;move data to user buffer
        jmp     dexit   ;jump to exit from read write
;
;       write one block
;
wrtsec:
        xchg            ;swap DE HL
        call    mov128  ;move 128 byte from th user's buffer to BUF
        lxi     h,ctb+3 ;set diskette write command
        mvi     m,wcom
        DCX     H
execute:
        call    diskette;execute diskette operation
dexit:
        pop     b       ;restore all registers
        pop     d
        pop     h
        ret             ;exit from read/write operation
$e
;
;       single density read/write
;
single:
        lxi     h,ctb+7 ;set pointers for trasfering requested parameters
        lxi     d,rdma+1;to the current controlblock CTB
        mvi     b,4     ;numbers of parameters to be transfered
sloop:
        ldax    d       ;get requested parameter
        mov     m,a     ;set current parameter
        dcx     h       ;update pointers
        dcx     d
        dcr     b       ;update counter
        jnz     sloop   ;loop until all parameters moved
        lda     rfunc   ;get requested operation
        mvi     m,rcom  ;set read command
        ana     a       ;read?
        jz      s1      ;yes
        mvi     m,wcom  ;no, set write command
s1:
        dcx     h       ;udate pointers
        LDAX    D
        MOV     M,A
;
;       the exit from single density is done through the common diskette
;       execute and restore all registers in the main loop
;
        jmp     execute ;execute diskette command, and restore all registers
$e
;*******************************************************************************
;
;       move 128 byte
;
;       input registers:        HL pointer to destination buffer
;                               DE pointer to source buffer
;
;       input parameters:       non
;
;       output parameters:      non
;
;       output registers:       non
;
;       changed registers:      A, B, C, D, E, H, L and FLAGS
;
;*******************************************************************************
;
mov128:
        mvi     b,128   ;counter
mloop:
        ldax    d       ;get byte from source buffer
        mov     m,a     ;move data to destination buffer
        inx     h       ;update pointers
        inx     d
        dcr     b       ;update counter
        jnz     mloop   ;continue until finiched
;
        sub     a       ;clear error message
        ret             ;exit from move 128 byte
$e
;*******************************************************************************
;
;       diskette sector address convert
;
;       convert sector parameter to side, density and sector value
;
;       input registers:
;                               A = sector address
;       input parameters:
;                               RTRACK requested track address
;       output parameters:
;                               non
;       output registers:
;                               B side,density and sector length parameters
;                               A sector address
;       changed registers:
;                               A, B, C, and FLAGS
;
;*******************************************************************************
;
str:
        mov     c,a     ;save sector address
        inr     a       ;+1
        rar             ;/2
        ani     7fh     ;remove most sign. bit
        mov     b,a     ;save converted sector address
        lda     rtrack  ;get requested track address
        rar             ;carry set if low byte = 1, side info
        mov     a,b     ;restore sector address
        mvi     b,90h   ;set double density, 256 byte/sector side zero
;
        rnc             ;exit from str, if side zero
;
        mvi     b,98h   ;set double density, 256 byte/sector side one
;
        ret             ;exit from str
$e
;*******************************************************************************
;
;       execute diskette command
;
;       input registers:
;                               HL pointer to CTB + 2
;       input parameters:
;                               CTB filled in
;       ouput parameters:
;                               CTB and CTB+1 contains status info
;       exit registers:
;                               A=status0 minus bit 7
;       changed registers:
;                               A and FLAGS
;
;*******************************************************************************
;
Diskette:               ;wait until diskette controller ready
        in      dio     ;get diskette controller status
        ral             ;busy?
        jnc     diskette;yes, wait until ready
        mov     a,h     ;ctb+2 address high byte
        out     dio     ;transfer to controller
;
        MVI     A,10
WAIT1:
        DCR     A
        JNZ     WAIT1
;
        mov     a,l     ;second part of CTB+2 address (low byte)
        out     dio     ;tranfer to diskette controller
;
;       wait until diskette operation is completed
;
wait3:                  ;wait until operation is completed
        in      dio     ;read diskette status
        ral             ;ready?
        jnc     wait3   ;no, wait until ready
        lda     ctb     ;get status
        ani     7Fh     ;error?
        rz              ;no, exit with A = 0
;
;       error exit
;
error:
        lxi     h,ctb+2
        mvi     m,-1    ;set unit parameter to illegal value to force unit
                        ;changed operation on next diskette operation
        ret             ;error exit, A <> 0
        end
